<?php

require_once __DIR__.DIRECTORY_SEPARATOR.'udp.php';

class scp extends udp
{
    private $share = '/kyo';
    const PACKET_DATA = 10;
    const PACKET_DATA_ACK = 11;
    static private $errstr = array(
       '用户名和密码验证失败!',
       '目标文件不存在或没有权限!',
       '传输异常!'
    );

    public function __construct($addr, $port)
    {
        parent::__construct($addr, $port);
    }

    public function server($share = null)
    {
        if ($share != null)
            $this->share = $share;
        $this->srv(array('scp', 'srv_handle'), $this);
    }

    public function client($packet, $dstfile)
    {
        $packet = $this->cli($packet);

        if ($packet === FALSE) {
            fprintf(STDERR, "服务器连接失败!\n");
            return 0;
        }

        if ($packet['type'] == udp::PACKET_ERROR) {
            fprintf(STDERR, "%s\n", self::$errstr[$packet['data']]);
            return 0;
        }

        $data = "";
        $count = 0;
        while (1) {
            $packet = $this->recv(null, scp::PACKET_ALL, 10000);
            if ($packet === FALSE
                || $packet['type'] == udp::PACKET_ERROR) {
                fprintf(STDERR, "传输异常\n");
                return 0;
            }
            if ($packet['type'] == udp::PACKET_DISCONNECT)
                break;

            printf("count = %d\n", ++$count);

            $data .= $packet['data'];
            $this->send(null, scp::PACKET_DATA_ACK);
        }

        file_put_contents($dstfile, $data);
    }


    public function srv_handle($cli, $obj, & $data)
    {
        printf("recv[%s:%d] conn: %s\n", $cli['addr'],
                 $cli['port'], $cli['conn']);

        $mes = explode("\n", $cli['conn']);

        if ($mes[0] != "root" || $mes[1] != "123") {
            echo "user & passwd", PHP_EOL;
            $obj->send($cli['sd'], udp::PACKET_ERROR, "0");
            return 0;
        }

        $s = file_get_contents($data->share.DIRECTORY_SEPARATOR.$mes[2]);
        if ($s === FALSE) {
            echo "filename", PHP_EOL;
            $obj->send($cli['sd'], udp::PACKET_ERROR, "1");
            return 0;
        }
        $len = strlen($s);

        // echo "check user & passwd success!\n";
        $ret = $obj->send($cli['sd'], udp::PACKET_CONN_ACK, $len);
        echo 'send conn ack: ', $ret, PHP_EOL;

        $start = 0;
        $data_len = 512;
        while ($start < $len) {
            $content = substr($s, $start, $data_len);
            $start += strlen($content);
            $obj->send($cli['sd'], scp::PACKET_DATA, $content);

            $packet = $obj->recv($cli['sd'], scp::PACKET_DATA_ACK);
            if ($packet === FALSE) {
                $obj->send($cli['sd'], udp::PACKET_ERROR, "2");
                return 0;
            }
        }

        $obj->send($cli['sd'], udp::PACKET_DISCONNECT);
    }
}

